CmdUtils.CreateCommand( {
    name:
        'bookmark',
    author: {
        name: 'Stephen Carmody',
        email: 'stephencarmody@gmail.com'
    },
    description:
        'Tags the current site using delicious',
    icon:
        'http://delicious.com/favicon.ico',
    help:
        'Tags the current site using delicious.',
    takes: {
        tag: noun_arb_text
    },


    /**
     * Command configuration settings.
     */
    _config: {
        cookie_manager: Components.classes["@mozilla.org/cookiemanager;1"]
                        .getService(Components.interfaces.nsICookieManager),

        // Base URL for the delicious v1 API
        api_base:        'https://api.del.icio.us/v1/',
 
        // Domain and name of the delicious login session cookie.
        cookie_domain:   '.delicious.com',
        cookie_name:     '_user',

        preview_columns: 5,
        highlight:       '#3274d0'
    },

    /**
     * Cache for queries.
     */
    _cache: {
      pblock:          undefined,
      tag:             undefined,
      space:           false,
      title:           undefined
    },

    /**
     * Gets the Delicious login session cookie.
     */
    _getUserCookie: function() {
        var iter = cmd_bookmark._config.cookie_manager.enumerator;
        while (iter.hasMoreElements()) {
            var cookie = iter.getNext();
            if( cookie instanceof Components.interfaces.nsICookie &&
                cookie.host.indexOf(this._config.cookie_domain) != -1 &&
                cookie.name == this._config.cookie_name) {
                return decodeURIComponent(cookie.value);
            }
        }
    },

    /**
     * Calls the specified Delicious V1 API command.
     */
    _query: function(cmd, callback) {
        // Use cache if available
        if (this._cache[cmd]!=undefined) {
            return callback(this._cache[cmd]);
        }
       
        var win = context.focusedWindow;
        var user_agent = win.navigator.userAgent + ';Ubiquity-bookmark';
   
        // DEBUG: To show when remote queries are made
        displayMessage('delicious -> '+cmd+')');
       
        jQuery.ajax({
            type: "POST",
            url: this._config.api_base + cmd,
            data: {_user: this._getUserCookie()},
            username: 'cookie',
            password: 'cookie',
            beforeSend: function( req ) {
                req.setRequestHeader("User-Agent", user_agent);
            },
            error: function() {
                displayMessage('Error querying delicious');
            },
            success: function(xml) {
                callback(xml);
            }
        });
    },

    /**
     * Callback for Delicious query for tags.
     */
    _tags: function(xml) {
        var tags     = jQuery(xml).find('tags tag');
        var maxcount = 0;
        var matches  = new Array();

        // Cache the results of the tags query
        cmd_bookmark._cache['tags/get'] = xml;

        // Preparse tags
        tags.each( function() {
            var tag = jQuery(this);
            var tagname = tag.attr('tag');
            var count = tag.attr('count');
            if (count > maxcount) {
                maxcount = count;
            }
            if (tagname.substring(0, cmd_bookmark._cache.tag.length) == cmd_bookmark._cache.tag) {
                matches[matches.length] = tagname;
            }
        });
       
        if (!cmd_bookmark._cache.space || matches.length == 0) {
            // Show the tag cloud
            cmd_bookmark._tagCloud(tags, maxcount);
        } else {
            // Show the matched tags posts
            cmd_bookmark._cache.pblock.innerHTML = '';
            for (i in matches) {
                cmd_bookmark._query('posts/recent?tag=' + matches[i], cmd_bookmark._posts);
            }
        }
    },
   
    /**
     * Writes the resolved template to the preview.
     */
    _tagTemplate: function(tag, count, maxcount) {
        var query = cmd_bookmark._cache.tag;
        var percent = 70 + parseInt((count / maxcount) * 30)
        var template = '<font style="font-size:${percent}%">${tag}</font>&nbsp;&nbsp;&nbsp;&nbsp;';
        var colour = cmd_bookmark._config['highlight'];
        var highlight = '<span style="background-color:' + colour + '">' + query + '</span>';
        var label = (tag.substring(0, query.length) == query) ? tag.replace(query, highlight) : tag;

        return CmdUtils.renderTemplate(template, {
            percent:   percent,
            tag:       label
        });
    },

    /**
     * Renders the tag cloud preview.
     */
    _tagCloud: function(tags, maxcount) {
        var column    = 0;
        var preview   = '['+this._cache.tag+'|'+this._cache.title+']';
       
        tags.each( function() {
            var tag = jQuery(this);
            preview += cmd_bookmark._tagTemplate(tag.attr('tag'), tag.attr('count'), maxcount);
            if (column++ == cmd_bookmark._config['preview_columns']) {
                column = 0;
                preview += '<br/>';
            }
        });

        cmd_bookmark._cache.pblock.innerHTML = preview;
    },

    /**
     * Writes the resolved template to the preview.
     */
    _postTemplate: function(href, desc) {
        var template = '<a href="${href}"><font style="font-size:70%">${desc}</font><br/><font style="font-size:70%;color:${colour}">${href}</font></a><br/>';

        return CmdUtils.renderTemplate(template, {
            colour: cmd_bookmark._config['highlight'],
            href: href,
            desc: desc
        });
    },

    /**
     * Callback for Delicious query for posts. Renders the tag posts preview.
     */
    _posts: function(xml) {
        var posts   = jQuery(xml).find('posts');
        var tag     = posts.attr('tag');
        var preview = cmd_bookmark._tagTemplate(tag, 3, 2) + '<br/>';

        // Cache the results of the posts query
        cmd_bookmark._cache['posts/recent?tag='+tag] = xml;

        posts.find('post').each( function() {
            var post = jQuery(this);
            preview += cmd_bookmark._postTemplate(post.attr('href'), post.attr('description'));
        });

        cmd_bookmark._cache.pblock.innerHTML += preview + '<br/>';
    },

    /**
     * Present a preview of the bookmark under construction during the course
     * of composing the command.
     */
    preview: function(pblock, tag) {
      var space = tag.text.indexOf(' ');

      this._cache.pblock = pblock;
      this._cache.tag = tag.text;

      if (space > 0) {
          this._cache.space = true;
          this._cache.tag = tag.text.substring(0, space);
          if (space < tag.text.length-1) {
              this._cache.title = tag.text.substring(space+1, tag.text.length);
          }
      }

      // Get the tags
      this._query('tags/get', this._tags);
    }

});

